//
//  HACKLineView.m
//  Pods
//
//  Created by Hotacool on 2017/9/1.
//
//

#import "HACKLineView.h"
#import "HACKLineEntry.h"
#import "HACIndexEntry.h"
#import "HACBasicComponents.h"
#import "HACChartDefine.h"
#import "HACBasicInfoEntry.h"

NSString *const HACKLineViewDataLabel = @"HACKLineData";
NSString *const HACKLineViewMADataLabel = @"HACKLineMAData";

static const NSUInteger HACKLineViewLineCount = 3; //5，10，20均线
@interface HACKLineView ()
/** k线数据 */
@property (nonatomic, copy) NSArray<HACKLineEntry*> *kLineData;
/** 均线数据 */
@property (nonatomic, copy) NSArray<HACKLineMAEntry*> *kLineMAData;
/** 画线点数据 */
@property (nonatomic, strong) NSMutableArray *lineDrawingData;
/** 画柱形图数据 */
@property (nonatomic, strong) NSMutableArray *rectDrawingData;

@end

@implementation HACKLineView

- (void)setUp {
    [super setUp];
    // 初始化页面属性
    self.backgroundColor = [UIColor clearColor];
    self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    self.xAxisCount = 5;
    self.yAxisCount = 5;
    self.visualCount = 50;
    CGFloat singleWidth = FormatValueWithRemain(CGRectGetWidth(self.frame) / self.visualCount, 3);
    self.singleWidth = singleWidth;
    
    _rectRenderer = [[HACRectRenderer alloc] initWithDataProvider:self];
    _lineRenderer = [[HACLineRenderer alloc] initWithDataProvider:self];
}

- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];
    
}

- (NSInteger)actualCount {
    return _kLineData?_kLineData.count:0;
}

- (void)setData:(HACChartData *)data {
    if (!data&&data.dataSets.count==2) {
        return;
    }
    //k线数据
    _kLineData = (NSArray<HACKLineEntry*>*)[data dataSetWithLabel:HACKLineViewDataLabel].values;
    _kLineMAData = (NSArray<HACKLineMAEntry*>*)[data dataSetWithLabel:HACKLineViewMADataLabel].values;
    HACChartDataSet *tmp = [data dataSetWithLabel:HACBasicDataLabel];
    self.basicInfoData = tmp?(HACBasicInfoEntry*)tmp.values.firstObject:nil;
    
    //处理数据为 5，10，20均线
    _lineDrawingData = [NSMutableArray arrayWithCapacity:HACKLineViewLineCount];
    for (NSInteger index = 0; index < HACKLineViewLineCount; index++) {
        HACLineComponents *lineItem = [[HACLineComponents alloc] init];
        lineItem.isCurve = YES;
        switch (index) {
            case 0: {
                lineItem.lineColor = [UIColor blueColor];
                break;
            }
            case 1: {
                lineItem.lineColor = [UIColor orangeColor];
                break;
            }
            case 2: {
                lineItem.lineColor = [UIColor redColor];
                break;
            }
            default:
                break;
        }
        lineItem.index = index;
        [_lineDrawingData addObject:lineItem];
    }
    self.startIndex = MAX(0, self.actualCount - self.visualCount);
    self.endIndex = MAX(self.visualCount, self.actualCount - 1);
    [super setData:data];
}

- (void)clean {
    _kLineData = nil;
    _kLineMAData = nil;
    _lineDrawingData = nil;
    self.startIndex = 0;
    self.endIndex = 0;
    [super clean];
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.rectRenderer drawInRect:rect context:context];
    [self.lineRenderer drawInRect:rect context:context];
}

#pragma mark - provider
- (NSArray *)rectDatasInRect:(CGRect)rect {
    if (self.actualCount == 0)
        return nil;
    
    self.rectDrawingData = [NSMutableArray array];
    CGFloat x, open, close, max, min;
    
    HACKLineEntry *pointData, *lastData;
    for (NSInteger i = self.startIndex; i <= self.endIndex && i < self.actualCount; i ++) {
        pointData = self.kLineData[i];
        HACRectComponents *rectItem = [[HACRectComponents alloc] init];
        rectItem.valueType = [self calculatorValueType:pointData lastData:lastData];
        rectItem.lineColor = [self colorWithValueType:rectItem.valueType];
        rectItem.isSoildFill = rectItem.valueType != DrawingUpValue;
        //偏移，转化到0~visualCount范围中
        NSInteger idx = [self relativeIdxFromIndex:i];
        x = [self xPointForIndex:idx inRect:self.pointRect];
        open = [self calculatorYForValue:pointData.openPrice min:self.minValue max:self.maxValue inRect:self.pointRect];
        close = [self calculatorYForValue:pointData.closePrice min:self.minValue max:self.maxValue inRect:self.pointRect];
        max = [self calculatorYForValue:pointData.maxPrice min:self.minValue max:self.maxValue inRect:self.pointRect];
        min = [self calculatorYForValue:pointData.minPrice min:self.minValue max:self.maxValue inRect:self.pointRect];
        rectItem.pillarRect = CGRectMake(x, MIN(open, close), self.singleWidth - self.itemsSpace, MAX(1, ABS(open - close)));// 保证高度至少为1
        rectItem.center = CGRectGetMidX(rectItem.pillarRect);
        
        CGLine upLine, downLine;
        if (rectItem.valueType == DrawingUpValue) {
            upLine = CGLineMake(rectItem.center, max, rectItem.center, close);
            downLine = CGLineMake(rectItem.center, min, rectItem.center, open);
        } else {
            upLine = CGLineMake(rectItem.center, max, rectItem.center, open);
            downLine = CGLineMake(rectItem.center, min, rectItem.center, close);
        }
        
        rectItem.line1 = upLine;
        rectItem.line2 = downLine;
        
        [self.rectDrawingData addObject:rectItem];
    }
    
    return self.rectDrawingData;
}

- (NSArray *)lineDatasInRect:(CGRect)rect {
    if (!self.data || [self lineValueForItem:nil lineIndex:0] == kDrawingInvaildValue) // 返回无效数据不做默认处理
        return nil;
    
    for (HACLineComponents *lineItem in self.lineDrawingData) {
        lineItem.pointCount = (self.endIndex - self.startIndex) + 1;
        NSMutableArray *pointsArray = [NSMutableArray array];
        
        for (NSInteger i = self.startIndex; i <= self.endIndex && i < self.actualCount; i++) {
            id pointData = self.kLineMAData[i];
            CGFloat x = 0.0, y = 0.0;
            //偏移，转化到0~visualCount范围中
            NSInteger idx = [self relativeIdxFromIndex:i];
            x = [self xPointForIndex:idx inRect:self.pointRect];
            if (self.singleWidth > 0) {
                // 如果已经绘制rect，需要偏移1/2 singleWidth实现居中
                x += self.singleWidth / 2;
            }
            CGFloat value = [self lineValueForItem:pointData lineIndex:lineItem.index];
            y = [self calculatorYForValue:value min:self.minValue max:self.maxValue inRect:self.pointRect];
            [pointsArray addObject:NSStringFromCGPoint(CGPointMake(x, y))];
        }
        lineItem.pointArray = pointsArray;
    }
    return self.lineDrawingData;
}

#pragma mark -- calculate
- (DrawingValueType)calculatorValueType:(HACKLineEntry *)currentData lastData:(HACKLineEntry *)prePointData {
    if (currentData.closePrice > currentData.openPrice)
        return DrawingUpValue;
    else if (currentData.closePrice < currentData.openPrice)
        return DrawingDownValue;
    else // 如果收盘价＝开盘价 ，根据昨收价判断
    {
        if (currentData.closePrice > prePointData.closePrice)
            return DrawingUpValue;
        else if (currentData.closePrice < prePointData.closePrice)
            return DrawingDownValue;
        else // 如果跟昨收价还相同，保持前一天一样的逻辑
            return (DrawingValueType)prePointData.closePrice >= prePointData.openPrice;
    }
    return DrawingUpValue;
}

// 计算最大，最小值
- (void)calculateLimitValue {
    CGFloat max = FLT_MIN;
    CGFloat min = FLT_MAX;
    CGFloat value;
    
    HACKLineMAEntry *maData;
    HACKLineEntry *klineData;
    for (NSInteger i = self.startIndex; i <= self.endIndex && i < self.actualCount; i++) {
        maData = self.kLineMAData[i];
        klineData = self.kLineData[i];
        
        CGFloat maxIdx = [maData maxIdxValue];
        CGFloat maxKLine = klineData.maxPrice;
        value = (maxIdx != kDrawingInvaildValue) ? MAX(maxKLine, maxIdx) : maxKLine;
        if (value != kDrawingInvaildValue && value > max) {
            max = value;
        }
        CGFloat minIdx = [maData minIdxValue];
        CGFloat mixKLine = klineData.minPrice;
        value = (minIdx != kDrawingInvaildValue) ? MIN(mixKLine, minIdx) : mixKLine;
        if (value != kDrawingInvaildValue && value < min) {
            min = value;
        }
    }
    self.maxValue = (max == FLT_MIN) ? .0 : max;
    self.minValue = (min == FLT_MAX) ? .0 : min;
//    //调整位置
//    if (_basicInfoData&&self.maxValue!=0&&self.minValue!=0) {
//        float base = _basicInfoData.previousPrice;
//        float a = ABS(self.maxValue - base);
//        float b = ABS(base - self.minValue);
//        if (a>b) {
//            self.minValue = base - a;
//        } else {
//            self.maxValue = base + b;
//        }
//    }
}
- (CGFloat)lineValueForItem:(HACIndexEntry *)data lineIndex:(NSInteger)index {
    CGFloat value = [data getIdxFromIdxResult:index];
    return value;
}

#pragma mark -- api
- (NSUInteger)indexAtChartForCoordinate:(CGPoint)point {
    NSInteger focusIndex = [super indexAtChartForCoordinate:point];
    
    CGFloat offsetX = point.x - CGRectGetMinX(self.frame) - CGRectGetMinX(self.pointRect);
    focusIndex = offsetX / self.singleWidth;
    focusIndex = MAX(MIN(focusIndex, self.endIndex-self.startIndex), 0);
    return focusIndex;
}

- (CGPoint)pointAtChartForIndex:(NSUInteger)index {
    CGPoint point = [super pointAtChartForIndex:index];
    if (self.rectDrawingData&&self.rectDrawingData.count>index) {
        HACRectComponents *rectItem = self.rectDrawingData[index];
        point.x = rectItem.pillarRect.origin.x+rectItem.pillarRect.size.width/2;
        if (rectItem.valueType == DrawingUpValue) {
            point.y = rectItem.pillarRect.origin.y;
        } else {
            point.y = rectItem.pillarRect.origin.y + rectItem.pillarRect.size.height;
        }
    }
    return point;
}

- (HACChartDataEntry*)dataAtChartForCoordinate:(CGPoint)point {
    HACChartDataEntry *indexData = [super dataAtChartForCoordinate:point];
    NSUInteger focusIndex = [self indexAtChartForCoordinate:point];
    if (self.kLineData && focusIndex < self.kLineData.count) {
        indexData = self.kLineData[focusIndex];
    }
    return indexData;
}

- (HACChartDataEntry*)dataAtChartForIndex:(NSUInteger)focusIndex {
    HACChartDataEntry *indexData = [super dataAtChartForIndex:focusIndex];
    if (self.kLineData && focusIndex < self.kLineData.count) {
        indexData = self.kLineData[focusIndex];
    }
    return indexData;
}
@end
